﻿using System.Drawing.Drawing2D;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System;
using System.Web;

namespace Marbles.Core.Web.Images
{
    public class ImageHandler : HttpHandlerBase, IHttpHandler
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            string filename = string.Empty;
            string mappedfilename = string.Empty;
            int width = 0;
            int height = 0;

            if (context.Request.Params["f"] != null) { filename = context.Request.Params["f"].Trim(); }
            if (context.Request.Params["w"] != null) { width = Convert.ToInt32(context.Request.Params["w"].Trim()); }
            if (context.Request.Params["h"] != null) { height = Convert.ToInt32(context.Request.Params["h"].Trim()); }

            if (filename == string.Empty) { throw new HttpException(404, "File not found"); }

            mappedfilename = context.Server.MapPath(filename);

            if (!File.Exists(mappedfilename))
            {
                if (filename.Contains("/"))
                {
                    throw new HttpException(404, "File not found");
                }

                mappedfilename = context.Server.MapPath(string.Format("/Resources/{0}", filename));
                if (!File.Exists(mappedfilename)) { throw new HttpException(404, "File not found"); }
            }

            FileStream fs = new FileStream(mappedfilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            Bitmap bmp = new Bitmap(fs);
            fs.Close();

            if ((width == 0) && (height == 0)) { width = bmp.Width; height = bmp.Height; }
            if (height == 0) { height = GetAspectRatioSize(bmp, width, true); }
            if (width == 0) { width = GetAspectRatioSize(bmp, height, false); }

            if ((width == bmp.Width) && (height == bmp.Height))
            {
                SaveToOutputStream(context, bmp, bmp.RawFormat);                
            }
            else
            {
                Bitmap destBmp = new Bitmap(width, height);
                Graphics g = Graphics.FromImage(destBmp);
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(bmp, 0, 0, destBmp.Width, destBmp.Height);
                g.Dispose();
                SaveToOutputStream(context, destBmp, bmp.RawFormat);
                destBmp.Dispose();
            }

            context.Response.Flush();
            bmp.Dispose();
        }

        public static void SaveToOutputStream(HttpContext context, Bitmap bmp, ImageFormat SourceImageFormat)
        {
            Bitmap bmp1 = new Bitmap(bmp);
            context.Response.Clear();
            context.Response.AddHeader("cache-control", "no-cache");
            context.Response.AddHeader("pragma", "no-cache");
            context.Response.AddHeader("expires", "0");
            context.Response.ContentType = GetContentType(SourceImageFormat);
            context.Response.BufferOutput = true;

            if (SourceImageFormat == ImageFormat.Png)
            {
                MemoryStream ms = new MemoryStream();
                bmp1.Save(ms, SourceImageFormat);
                ms.WriteTo(context.Response.OutputStream);
                ms.Dispose();
                bmp1.Dispose();
            }
            else
            {
                bmp1.Save(context.Response.OutputStream, SourceImageFormat);
                bmp1.Dispose();
            }
        }

        private int GetAspectRatioSize(Bitmap bmp, int size, bool useWidth)
        {
            int sourceWidth = bmp.Width;
            int sourceHeight = bmp.Height;
            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)size / (float)sourceWidth);
            nPercentH = ((float)size / (float)sourceHeight);

            if (useWidth)
            {
                nPercent = nPercentW;
                return (int)(sourceHeight * nPercent);
            }
            else
            {
                nPercent = nPercentH;
                return (int)(sourceWidth * nPercent);

            }
        }

        private static string GetContentType(System.Drawing.Imaging.ImageFormat Format)
        {
            if (Format == ImageFormat.Bmp) { return "image/bmp"; }
            if (Format == ImageFormat.Emf) { return "image/x-emf"; }
            if (Format == ImageFormat.Exif) { return "image/exif"; }
            if (Format == ImageFormat.Gif) { return "image/gif"; }
            if (Format == ImageFormat.Icon) { return "image/ico"; }
            if (Format == ImageFormat.Jpeg) { return "image/jpeg"; }
            if (Format == ImageFormat.Png) { return "image/png"; }
            if (Format == ImageFormat.Tiff) { return "image/tiff"; }
            if (Format == ImageFormat.Wmf) { return "image/wmf"; }

            return "image/bmp";
        }

        public override void Register()
        {
            RegisterHttpHandler("Image.axd", "Marbles.Core.Web.Images.ImageHandler", "GET,HEAD");
        }

    }
}
